home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 1 / BBS in a box - Trilogy I.iso / Files / Art / Art Tools / Pict Convert / Pict Convert.p < prev    next >
Encoding:
Text File  |  1993-05-05  |  11.9 KB  |  273 lines  |  [TEXT/PJMM]

  1. Program PictConvert;
  2.  
  3.     Uses
  4.         AppleTalk, Aliases, Processes, PPCToolBox, EPPC, Notification, AppleEvents;
  5.  
  6.     Var
  7.         TargetApp, TargetDir, LogFile: FSSpec;
  8.         Err: OSErr;
  9.         HomeVolName, TargVolName: Str255;
  10.         HomeVolNamePtr, TargVolNamePtr: StringPtr;
  11.         HomeVRefNum, TargVRefNum, x, LogRef: Integer;
  12.         HomeDirID, TempFreeBytes: LongInt;
  13.         TargetPB: CInfoPBRec;
  14.         TargetPBPtr: CInfoPBPtr;
  15.         TargIsFolder, WasAliased, GotAppDied: Boolean;
  16.         TheEvent: EventRecord;
  17.         TheKeys: KeyMap;
  18.  
  19.  
  20.  
  21.     Function DoAppDiedEvent (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
  22.     Begin
  23.         GotAppDied := True;
  24.         DoAppDiedEvent := NoErr;
  25.     End;
  26.  
  27.     Function DoAEOpen (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
  28.     Begin
  29.         DoAEOpen := NoErr;
  30.     End;
  31.  
  32.     Function DoAEOpenDoc (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
  33.     Begin
  34.         DoAEOpenDoc := errAEEventNotHandled;
  35.     End;
  36.  
  37.     Function DoAEPrintDoc (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
  38.     Begin
  39.         DoAEPrintDoc := errAEEventNotHandled;
  40.     End;
  41.  
  42.     Function DoAEQuit (TheAppleEvent, Reply: AppleEvent; Refcon: LongInt): OSErr;
  43.     Begin
  44.         DoAEQuit := errAEEventNotHandled;
  45.     End;
  46. {These are all AppleEvent handler routines -- the only one we need     }
  47. {is the DoAppDied event.  The other four are the 'required' AppleEvents}
  48.  
  49.  
  50.     Procedure ConvertFile (Targ: FSSpec);
  51.         Var
  52.             theAEvent: AppleEvent;
  53.             tempDesc, launchDesc, docDesc: AEDesc;
  54.             docDescList: AEDescList;
  55.             tempPSN, TargetPSN: ProcessSerialNumber;
  56.             docAlias: AliasHandle;
  57.             launchParams: LaunchParamBlockRec;
  58.             appParams: AppParametersPtr;
  59.             Qel: EvQElPtr;
  60.             x: LongInt;
  61.             Nix: Boolean;
  62.             WriteData: Array[1..33] Of Byte;
  63.  
  64.     Begin
  65.         tempDesc.dataHandle := Nil;
  66.         theAEvent.dataHandle := Nil;
  67.         docDescList.dataHandle := Nil;
  68.         docAlias := Nil;
  69.         tempPSN.highLongOfPSN := 0;
  70.         tempPSN.lowLongOfPSN := kCurrentProcess;
  71.         Err := AECreateDesc(typeProcessSerialNumber, @tempPSN, SizeOf(ProcessSerialNumber), tempDesc);
  72.         Err := AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, tempDesc, kAutoGenerateReturnID, kAnyTransactionID, theAEvent);
  73.         Err := AEDisposeDesc(tempDesc);
  74.         Err := AECreateList(Nil, 0, False, docDescList);
  75.         Err := NewAlias(Nil, Targ, docAlias);
  76.         docDesc.descriptorType := typeAlias;
  77.         docDesc.dataHandle := Handle(docAlias);
  78.         Err := AEPutDesc(docDescList, 0, docDesc);
  79.         DisposHandle(Handle(docAlias));
  80.         docAlias := Nil;
  81.         Err := AEPutParamDesc(theAEvent, keyDirectObject, docDescList);
  82.         Err := AEDisposeDesc(docDescList);
  83.         Err := AECoerceDesc(theAEvent, typeAppParameters, launchDesc);
  84.         Err := AEDisposeDesc(theAEvent);
  85.         HLock(Handle(launchDesc.dataHandle));
  86.         appParams := AppParametersPtr(launchDesc.dataHandle^);
  87.         With launchParams Do
  88.             Begin
  89.                 launchBlockID := extendedBlock;
  90.                 launchEPBLength := extendedBlockLen;
  91.                 launchfileFlags := 0;
  92.                 launchControlFlags := launchContinue + launchNoFileFlags + launchUseMinimum + launchAllow24Bit;
  93.                 launchAppSpec := @TargetApp;
  94.                 launchAppParameters := appParams;
  95.             End;
  96.         Err := LaunchApplication(@launchParams);
  97.         HUnlock(Handle(launchDesc.dataHandle));
  98.         Err := AEDisposeDesc(launchDesc);
  99. {The credit for the above code goes to Forrest Tanaka and Pete Helm.  (Especially Pete,}
  100. {for making a Pascal conversion of Forrest's code)  The code was taken basically       }
  101. {verbatim from the "ProcDoggie" code found on the Developer's CD.  Don't ask me >how<  }
  102. {it works, it just does.  You go in with a file specification, and these wonderful     }
  103. {AppleEvent Manager calls do something with it so you can specify a document for the   }
  104. {Process Manager's 'LaunchApplication' call so the launched application can open the   }
  105. {file!  Pretty neat, huh?  Especially neat since the Process manager chapter of IM:    }
  106. {Processes mentions that it's possible, but doesn't give any samples.  This is a very  }
  107. {simple way of specifying one file for opening that some people might find more        }
  108. {digestable than the ProcDoggie code, which covers a much wider and complexly          }
  109. {structured example of the LaunchApplication call.  (and a whole ton of other stuff!)  }
  110.  
  111.         TargetPSN := launchParams.launchProcessSN;
  112. {we need this to keep an eye on our launched app.  read on...}
  113.  
  114.         Repeat
  115.             Nix := WaitNextEvent(EveryEvent, TheEvent, 200, Nil);
  116.             Err := GetFrontProcess(tempPSN);
  117.             Err := SameProcess(TargetPSN, tempPSN, Nix);
  118.             GetKeys(TheKeys)
  119.         Until ((Nix) Or (TheKeys[56]));
  120. {Translation: hang out and don't do anything until we see that our launched app has    }
  121. {made it to the foreground.  Otherwise it (the app) won't get the events we're about   }
  122. {to send.                                                                              }
  123.  
  124.         If (Not TheKeys[56]) Then
  125.             Begin
  126.                 Err := PPostEvent(3, Ord4('s'), Qel);  {Post a keydown for the letter 's' using       }
  127.                 Qel^.evtQModifiers := 384;             {PPostEvent so we can go back into the event   }
  128.                 x := 0;                                {and make it look like the Command key was used}
  129.                 With Targ Do                          {Efectively giving the forground app a 'Cmd-S' }
  130.                     Repeat
  131.                         x := x + 1;
  132.                         Err := PostEvent(3, Ord4(name[x]));  {Walk through the file name "typing" each letter}
  133.                     Until (name[x] = '.');               {up to the period.                              }
  134.                 Err := PostEvent(3, Ord4('g'));        {Gimme a 'g'! }
  135.                 Err := PostEvent(3, Ord4('i'));        {Gimme an 'i'!}
  136.                 Err := PostEvent(3, Ord4('f'));        {Gimme an 'f'!}
  137.                 x := TickCount + 300;
  138.                 While (x > TickCount) Do                              {Wait a few seconds for the app's}
  139.                     Nix := WaitNextEvent(EveryEvent, TheEvent, 0, Nil);   {dialog to catch up if need be.  }
  140.                 Err := PostEvent(3, 3);                                {Post 'Enter' key.  (keycode 3)  }
  141.                 Err := PPostEvent(3, Ord4('q'), Qel);
  142.                 Qel^.evtQModifiers := 384;             {Post a 'Cmd-Q' using the same method as before  }
  143.                                            {so app quits after finishing it's save command  }
  144.  
  145.                 GotAppDied := False;
  146.                 Repeat
  147.                     Nix := WaitNextEvent(EveryEvent, TheEvent, 2000, Nil);
  148.                     If (TheEvent.what = kHighLevelEvent) Then
  149.                         Err := AEProcessAppleEvent(TheEvent);
  150.                     GetKeys(TheKeys);
  151.                 Until ((GotAppDied) Or (TheKeys[56]));
  152. {Translation: hang out and do nothing until we recieve the 'Child Died' or 'App Died' event,}
  153. {telling us that our previously launched application has quit.                              }
  154.  
  155.                 If GotAppDied Then         {We assume the app died after completing it's task, so}
  156.                     Err := FSpDelete(Targ);    {we go ahead and delete the original file             }
  157.  
  158.                 Err := FlushVol(TargVolNamePtr, TargVRefNum);   {Update the volume after having a new file}
  159.                                                     {created and another deleted.             }
  160.                 For x := 1 To Length(Targ.Name) Do
  161.                     WriteData[x] := Byte(Targ.Name[x]);
  162.                 x := Length(Targ.Name) + 1;
  163.                 WriteData[x] := 13;
  164.                 Err := FSWrite(LogRef, x, @WriteData);   {Write name of converted file to our log file}
  165.             End;
  166.     End;
  167.  
  168.  
  169.     Procedure SearchDir (SVRefNum: Integer; SDirID: LongInt);
  170.         Var
  171.             GetCatErr: OSErr;
  172.             x: Integer;
  173.             SearchPB: CInfoPBRec;
  174.             SearchPBPtr: CInfoPBPtr;
  175.             SearchName: Str255;
  176.             SearchNamePtr: StringPtr;
  177.             SearchNeg: Boolean;
  178.             TargetFile: FSSpec;
  179.  
  180.     Begin
  181.         SearchNamePtr := @SearchName;
  182.         SearchPBPtr := @SearchPB;
  183.         Repeat
  184.             SearchNeg := True;             {Assume we won't find a target file}
  185.             x := 1;
  186.             With SearchPB Do              {Starting with first item in directory, (x) }
  187.                 Begin                        {Use PBGetCatInfo to see if item is a folder}
  188.                     ioCompletion := Nil;        {or file.  If it's a folder, call SearchDir }
  189.                     ioNamePtr := SearchNamePtr;  {recursively with folder info.  If it's a   }
  190.                     ioVRefNum := SVRefNum;       {file, see if it looks like a Pict, and if  }
  191.                     ioFDirIndex := x;            {so, call our conversion routine            }
  192.                     ioDirID := SDirID;
  193.                 End;
  194.             GetCatErr := PBGetCatInfo(SearchPBPtr, False);
  195.             If (GetCatErr = NoErr) Then
  196.                 Repeat
  197.                     If (BitTst(@SearchPB.ioFlAttrib, 3)) Then
  198.                         Begin {dir}
  199.                             SearchDir(SearchPB.ioVRefNum, SearchPB.ioDrDirID);
  200.                         End
  201.                     Else
  202.                         Begin {file}
  203.                             If (pos('.pict', SearchName) <> 0) Or (pos('.PICT', SearchName) <> 0) Then
  204.                                 Begin
  205.                                     SearchNeg := False;      {We found a target.  Reset search for this directory}
  206.                                     GetCatErr := fnfErr;
  207.                                     Err := FSMakeFSSpec(SearchPB.ioVRefNum, SearchPB.ioFlParID, SearchName, TargetFile);
  208.                                     ConvertFile(TargetFile);
  209.                                 End;
  210.                         End;
  211.                     x := x + 1;
  212.                     SearchPB.ioFDirIndex := x;
  213.                     SearchPB.ioDirID := SDirID;
  214.                     If (SearchNeg) Then                              {We don't want to call PBGetCatInfo if }
  215.                         GetCatErr := PBGetCatInfo(SearchPBPtr, False);   {we processed a target. dump out of    }
  216.                     GetKeys(TheKeys);                                 {loop to start over with this directory}
  217.                 Until ((GetCatErr = fnfErr) Or (TheKeys[56]));
  218.         Until ((SearchNeg) Or (TheKeys[56]));             {Search Directory until we get to the end}
  219.     End;                                               {or we find a target.  If we got to the  }
  220.                                                      {end, exit routine.  If we got (and      }
  221.                                                      {processed) a target, start over         }
  222. Begin
  223.     HomeVolNamePtr := @HomeVolName;
  224.     TargetPBPtr := @TargetPB;
  225.     TargVolNamePtr := @TargVolName;
  226.                                                                        {Create File Spec records}
  227.     Err := HGetVol(HomeVolNamePtr, HomeVRefNum, HomeDirID);               {for our app to be       }
  228.     Err := FSMakeFSSpec(HomeVRefNum, HomeDirID, 'Target App', TargetApp); {launched, directory to  }
  229.     Err := FSMakeFSSpec(HomeVRefNum, HomeDirID, 'Target Dir', TargetDir); {scan for files, and our }
  230.     Err := FSMakeFSSpec(HomeVRefNum, HomeDirID, 'Log File', LogFile);     {file for logging targets}
  231.  
  232.     Err := ResolveAliasFile(TargetDir, True, TargIsFolder, WasAliased);   {Make sure Target Dir    }
  233.                                                                        {really IS a directory   }
  234.                                                                        {and...}
  235.     If TargIsFolder Then                                                 {don't continue otherwise}
  236.         Begin
  237.             Err := AEInstallEventHandler(kCoreEventClass, kAEApplicationDied, @DoAppDiedEvent, 0, False);
  238.             Err := AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, @DoAEOpen, 0, False);
  239.             Err := AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, @DoAEOpenDoc, 0, False);
  240.             Err := AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, @DoAEPrintDoc, 0, False);
  241.             Err := AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, @DoAEQuit, 0, False);
  242. {Install our event handlers for the required events (that we don't use anyway)}
  243. {and the 'App Died' event.                                                    }
  244.  
  245.             x := -1;
  246.             Repeat
  247.                 Err := GetVInfo(x, TargVolNamePtr, TargVRefNum, TempFreeBytes);
  248.                 x := x - 1;
  249.             Until (TargVRefNum = TargetDir.VRefNum);
  250. {Get volume number and name for the target directory's volume so we can do FlushVol's for it}
  251. {later on.  Wish we could just use the volume refrence number, but oh well...               }
  252.  
  253.             Err := FSpDelete(LogFile);
  254.             Err := FSpCreate(LogFile, 'ttxt', 'TEXT', -1);   {Create our file for logging converted files}
  255.             Err := FSpOpenDF(LogFile, fsWrPerm, LogRef);     {obliterating any existing one.             }
  256.  
  257.             If (Err = NoErr) Then
  258.                 Begin
  259.                     With TargetPB Do
  260.                         Begin
  261.                             ioCompletion := Nil;
  262.                             ioNamePtr := @TargetDir.Name;
  263.                             ioVRefNum := TargetDir.VRefNum;
  264.                             ioFDirIndex := 0;
  265.                             ioDrDirID := TargetDir.ParID;
  266.                         End;                                             {Set things rolling by calling SearchDir}
  267.                     Err := PBGetCatInfo(TargetPBPtr, False);          {with the info on Target Dir.           }
  268.                     SearchDir(TargetPB.ioVRefNum, TargetPB.ioDrDirID);
  269.                     Err := FSClose(LogRef);
  270.                     Err := FlushVol(HomeVolNamePtr, HomeVRefNum);      {when done, close and flush our log file}
  271.                 End;
  272.         End;
  273. End.